'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _shallowequal = require('shallowequal');

var _shallowequal2 = _interopRequireDefault(_shallowequal);

var _addEventListener = require('../util/Dom/addEventListener');

var _addEventListener2 = _interopRequireDefault(_addEventListener);

var _miniStore = require('mini-store');

var _merge = require('lodash/merge');

var _merge2 = _interopRequireDefault(_merge);

var _componentClasses = require('component-classes');

var _componentClasses2 = _interopRequireDefault(_componentClasses);

var _utils = require('./utils');

var _ColumnManager = require('./ColumnManager');

var _ColumnManager2 = _interopRequireDefault(_ColumnManager);

var _HeadTable = require('./HeadTable');

var _HeadTable2 = _interopRequireDefault(_HeadTable);

var _BodyTable = require('./BodyTable');

var _BodyTable2 = _interopRequireDefault(_BodyTable);

var _ExpandableTable = require('./ExpandableTable');

var _ExpandableTable2 = _interopRequireDefault(_ExpandableTable);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var Table = function (_React$Component) {
  (0, _inherits3['default'])(Table, _React$Component);

  function Table(props) {
    (0, _classCallCheck3['default'])(this, Table);

    var _this = (0, _possibleConstructorReturn3['default'])(this, _React$Component.call(this, props));

    _this.state = {};

    _this.getRowKey = function (record, index) {
      var rowKey = _this.props.rowKey;
      var key = typeof rowKey === 'function' ? rowKey(record, index) : record[rowKey];
      (0, _utils.warningOnce)(key !== undefined, 'Each record in table should have a unique `key` prop,' + 'or set `rowKey` to an unique primary key.');
      return key === undefined ? index : key;
    };

    _this.handleWindowResize = function () {
      _this.syncFixedTableRowHeight();
      _this.setScrollPositionClassName();
    };

    _this.syncFixedTableRowHeight = function () {
      var tableRect = _this.tableNode.getBoundingClientRect();
      // If tableNode's height less than 0, suppose it is hidden and don't recalculate rowHeight.
      // see: https://github.com/ant-design/ant-design/issues/4836
      if (tableRect.height !== undefined && tableRect.height <= 0) {
        return;
      }
      var prefixCls = _this.props.prefixCls;

      var headRows = _this.headTable ? _this.headTable.querySelectorAll('thead') : _this.bodyTable.querySelectorAll('thead');
      var bodyRows = _this.bodyTable.querySelectorAll('.' + prefixCls + '-row') || [];
      var fixedColumnsHeadRowsHeight = [].map.call(headRows, function (row) {
        return row.getBoundingClientRect().height || 'auto';
      });
      var state = _this.store.getState();
      var fixedColumnsBodyRowsHeight = [].reduce.call(bodyRows, function (acc, row) {
        var rowKey = row.getAttribute('data-row-key');
        var height = row.getBoundingClientRect().height || state.fixedColumnsBodyRowsHeight[rowKey] || 'auto';
        acc[rowKey] = height;
        return acc;
      }, {});
      if ((0, _shallowequal2['default'])(state.fixedColumnsHeadRowsHeight, fixedColumnsHeadRowsHeight) && (0, _shallowequal2['default'])(state.fixedColumnsBodyRowsHeight, fixedColumnsBodyRowsHeight)) {
        return;
      }

      _this.store.setState({
        fixedColumnsHeadRowsHeight: fixedColumnsHeadRowsHeight,
        fixedColumnsBodyRowsHeight: fixedColumnsBodyRowsHeight
      });
    };

    _this.handleBodyScrollLeft = function (e) {
      // Fix https://github.com/ant-design/ant-design/issues/7635
      if (e.currentTarget !== e.target) {
        return;
      }
      var target = e.target;
      var _this$props$scroll = _this.props.scroll,
          scroll = _this$props$scroll === undefined ? {} : _this$props$scroll;
      var headTable = _this.headTable,
          bodyTable = _this.bodyTable;

      if (target.scrollLeft !== _this.lastScrollLeft && scroll.x) {
        if (target === bodyTable && headTable) {
          headTable.scrollLeft = target.scrollLeft;
        } else if (target === headTable && bodyTable) {
          bodyTable.scrollLeft = target.scrollLeft;
        }
        _this.setScrollPositionClassName();
      }
      // Remember last scrollLeft for scroll direction detecting.
      _this.lastScrollLeft = target.scrollLeft;
    };

    _this.handleBodyScrollTop = function (e) {
      var target = e.target;
      // Fix https://github.com/ant-design/ant-design/issues/9033
      if (e.currentTarget !== target) {
        return;
      }
      var _this$props$scroll2 = _this.props.scroll,
          scroll = _this$props$scroll2 === undefined ? {} : _this$props$scroll2;
      var headTable = _this.headTable,
          bodyTable = _this.bodyTable,
          fixedColumnsBodyLeft = _this.fixedColumnsBodyLeft,
          fixedColumnsBodyRight = _this.fixedColumnsBodyRight;

      if (target.scrollTop !== _this.lastScrollTop && scroll.y && target !== headTable) {
        var scrollTop = target.scrollTop;
        if (fixedColumnsBodyLeft && target !== fixedColumnsBodyLeft) {
          fixedColumnsBodyLeft.scrollTop = scrollTop;
        }
        if (fixedColumnsBodyRight && target !== fixedColumnsBodyRight) {
          fixedColumnsBodyRight.scrollTop = scrollTop;
        }
        if (bodyTable && target !== bodyTable) {
          bodyTable.scrollTop = scrollTop;
        }
      }
      // Remember last scrollTop for scroll direction detecting.
      _this.lastScrollTop = target.scrollTop;
    };

    _this.handleBodyScroll = function (e) {
      _this.handleBodyScrollLeft(e);
      _this.handleBodyScrollTop(e);
    };

    _this.handleWheel = function (event) {
      var _this$props$scroll3 = _this.props.scroll,
          scroll = _this$props$scroll3 === undefined ? {} : _this$props$scroll3;

      if (window.navigator.userAgent.match(/Trident\/7\./) && scroll.y) {
        event.preventDefault();
        var wd = event.deltaY;
        var target = event.target;
        var bodyTable = _this.bodyTable,
            fixedColumnsBodyLeft = _this.fixedColumnsBodyLeft,
            fixedColumnsBodyRight = _this.fixedColumnsBodyRight;

        var scrollTop = 0;

        if (_this.lastScrollTop) {
          scrollTop = _this.lastScrollTop + wd;
        } else {
          scrollTop = wd;
        }

        if (fixedColumnsBodyLeft && target !== fixedColumnsBodyLeft) {
          fixedColumnsBodyLeft.scrollTop = scrollTop;
        }
        if (fixedColumnsBodyRight && target !== fixedColumnsBodyRight) {
          fixedColumnsBodyRight.scrollTop = scrollTop;
        }
        if (bodyTable && target !== bodyTable) {
          bodyTable.scrollTop = scrollTop;
        }
      }
    };

    _this.saveRef = function (name) {
      return function (node) {
        _this[name] = node;
      };
    };

    ['onRowClick', 'onRowDoubleClick', 'onRowContextMenu', 'onRowMouseEnter', 'onRowMouseLeave'].forEach(function (name) {
      (0, _utils.warningOnce)(props[name] === undefined, name + ' is deprecated, please use onRow instead.');
    });

    (0, _utils.warningOnce)(props.getBodyWrapper === undefined, 'getBodyWrapper is deprecated, please use custom components instead.');

    _this.columnManager = new _ColumnManager2['default'](props.columns, props.children);

    _this.store = (0, _miniStore.create)({
      currentHoverKey: null,
      fixedColumnsHeadRowsHeight: [],
      fixedColumnsBodyRowsHeight: {}
    });

    _this.setScrollPosition('left');

    _this.debouncedWindowResize = (0, _utils.debounce)(_this.handleWindowResize, 150);
    return _this;
  }

  Table.prototype.getChildContext = function getChildContext() {
    return {
      table: {
        props: this.props,
        columnManager: this.columnManager,
        saveRef: this.saveRef,
        components: (0, _merge2['default'])({
          table: 'table',
          header: {
            wrapper: 'thead',
            row: 'tr',
            cell: 'th'
          },
          body: {
            wrapper: 'tbody',
            row: 'tr',
            cell: 'td'
          }
        }, this.props.components)
      }
    };
  };

  Table.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.columns && nextProps.columns !== prevState.columns) {
      return {
        columns: nextProps.columns,
        children: null
      };
    } else if (nextProps.children !== prevState.children) {
      return {
        columns: null,
        children: nextProps.children
      };
    }
    return null;
  };

  Table.prototype.componentDidMount = function componentDidMount() {
    if (this.columnManager.isAnyColumnsFixed()) {
      this.handleWindowResize();
      this.resizeEvent = (0, _addEventListener2['default'])(window, 'resize', this.debouncedWindowResize);
    }
  };

  Table.prototype.componentDidUpdate = function componentDidUpdate(prevProps) {
    if (this.columnManager.isAnyColumnsFixed()) {
      this.handleWindowResize();
      if (!this.resizeEvent) {
        this.resizeEvent = (0, _addEventListener2['default'])(window, 'resize', this.debouncedWindowResize);
      }
    }
    // when table changes to empty, reset scrollLeft
    if (prevProps.data.length > 0 && this.props.data.length === 0 && this.hasScrollX()) {
      this.resetScrollX();
    }
  };

  Table.prototype.componentWillUnmount = function componentWillUnmount() {
    if (this.resizeEvent) {
      this.resizeEvent.remove();
    }
    if (this.debouncedWindowResize) {
      this.debouncedWindowResize.cancel();
    }
  };

  Table.prototype.setScrollPosition = function setScrollPosition(position) {
    this.scrollPosition = position;
    if (this.tableNode) {
      var prefixCls = this.props.prefixCls;

      if (position === 'both') {
        (0, _componentClasses2['default'])(this.tableNode).remove(new RegExp('^' + prefixCls + '-scroll-position-.+$')).add(prefixCls + '-scroll-position-left').add(prefixCls + '-scroll-position-right');
      } else {
        (0, _componentClasses2['default'])(this.tableNode).remove(new RegExp('^' + prefixCls + '-scroll-position-.+$')).add(prefixCls + '-scroll-position-' + position);
      }
    }
  };

  Table.prototype.setScrollPositionClassName = function setScrollPositionClassName() {
    var node = this.bodyTable;
    var scrollToLeft = node.scrollLeft === 0;
    var scrollToRight = node.scrollLeft + 1 >= node.children[0].getBoundingClientRect().width - node.getBoundingClientRect().width;
    if (scrollToLeft && scrollToRight) {
      this.setScrollPosition('both');
    } else if (scrollToLeft) {
      this.setScrollPosition('left');
    } else if (scrollToRight) {
      this.setScrollPosition('right');
    } else if (this.scrollPosition !== 'middle') {
      this.setScrollPosition('middle');
    }
  };

  Table.prototype.resetScrollX = function resetScrollX() {
    if (this.headTable) {
      this.headTable.scrollLeft = 0;
    }
    if (this.bodyTable) {
      this.bodyTable.scrollLeft = 0;
    }
  };

  Table.prototype.hasScrollX = function hasScrollX() {
    var _props$scroll = this.props.scroll,
        scroll = _props$scroll === undefined ? {} : _props$scroll;

    return 'x' in scroll;
  };

  Table.prototype.renderMainTable = function renderMainTable() {
    var _props = this.props,
        scroll = _props.scroll,
        prefixCls = _props.prefixCls;

    var isAnyColumnsFixed = this.columnManager.isAnyColumnsFixed();
    var scrollable = isAnyColumnsFixed || scroll.x || scroll.y;

    var table = [this.renderTable({
      columns: this.columnManager.groupedColumns(),
      isAnyColumnsFixed: isAnyColumnsFixed
    }), this.renderEmptyText(), this.renderFooter()];

    return scrollable ? _react2['default'].createElement('div', { className: prefixCls + '-scroll' }, table) : table;
  };

  Table.prototype.renderLeftFixedTable = function renderLeftFixedTable() {
    var prefixCls = this.props.prefixCls;

    return _react2['default'].createElement('div', { className: prefixCls + '-fixed-left' }, this.renderTable({
      columns: this.columnManager.leftColumns(),
      fixed: 'left'
    }));
  };

  Table.prototype.renderRightFixedTable = function renderRightFixedTable() {
    var prefixCls = this.props.prefixCls;

    return _react2['default'].createElement('div', { className: prefixCls + '-fixed-right' }, this.renderTable({
      columns: this.columnManager.rightColumns(),
      fixed: 'right'
    }));
  };




  Table.prototype.renderTable = function renderTable(options) {
    var columns = options.columns,
        fixed = options.fixed,
        isAnyColumnsFixed = options.isAnyColumnsFixed;
    var _props2 = this.props,
        prefixCls = _props2.prefixCls,
        _props2$scroll = _props2.scroll,
        scroll = _props2$scroll === undefined ? {} : _props2$scroll,
        resizable = _props2.resizable;

    var tableClassName = scroll.x || fixed ? prefixCls + '-fixed' : '';

    var headTable = _react2['default'].createElement(_HeadTable2['default'], {
      key: 'head',
      columns: columns,
      fixed: fixed,
      tableClassName: tableClassName,
      handleBodyScrollLeft: this.handleBodyScrollLeft,
      expander: this.expander
    });

    var bodyTable = _react2['default'].createElement(_BodyTable2['default'], {
      key: 'body',
      columns: columns,
      fixed: fixed,
      resizable: resizable,
      tableClassName: tableClassName,
      getRowKey: this.getRowKey,
      handleWheel: this.handleWheel,
      handleBodyScroll: this.handleBodyScroll,
      expander: this.expander,
      isAnyColumnsFixed: isAnyColumnsFixed
    });

    return [headTable, bodyTable];
  };

  Table.prototype.renderTitle = function renderTitle() {
    var _props3 = this.props,
        title = _props3.title,
        prefixCls = _props3.prefixCls;

    return title ? _react2['default'].createElement('div', { className: prefixCls + '-title', key: 'title' }, title(this.props.data)) : null;
  };

  Table.prototype.renderFooter = function renderFooter() {
    var _props4 = this.props,
        footer = _props4.footer,
        prefixCls = _props4.prefixCls;

    return footer ? _react2['default'].createElement('div', { className: prefixCls + '-footer', key: 'footer' }, footer(this.props.data)) : null;
  };

  Table.prototype.renderEmptyText = function renderEmptyText() {
    var _props5 = this.props,
        emptyText = _props5.emptyText,
        prefixCls = _props5.prefixCls,
        data = _props5.data;

    if (data.length) {
      return null;
    }
    var emptyClassName = prefixCls + '-placeholder';
    return _react2['default'].createElement('div', { className: emptyClassName, key: 'emptyText' }, typeof emptyText === 'function' ? emptyText() : emptyText);
  };

  Table.prototype.render = function render() {
    var _this2 = this;

    var props = this.props;
    var prefixCls = props.prefixCls;

    if (this.state.columns) {
      this.columnManager.reset(props.columns);
    } else if (this.state.children) {
      this.columnManager.reset(null, props.children);
    }

    var className = props.prefixCls;
    if (props.className) {
      className += ' ' + props.className;
    }
    if (props.useFixedHeader || props.scroll && props.scroll.y) {
      className += ' ' + prefixCls + '-fixed-header';
    }
    if (this.scrollPosition === 'both') {
      className += ' ' + prefixCls + '-scroll-position-left ' + prefixCls + '-scroll-position-right';
    } else {
      className += ' ' + prefixCls + '-scroll-position-' + this.scrollPosition;
    }
    var hasLeftFixed = this.columnManager.isAnyColumnsLeftFixed();
    var hasRightFixed = this.columnManager.isAnyColumnsRightFixed();

    return _react2['default'].createElement(_miniStore.Provider, { store: this.store }, _react2['default'].createElement(_ExpandableTable2['default'], (0, _extends3['default'])({}, props, { columnManager: this.columnManager, getRowKey: this.getRowKey }), function (expander) {
      _this2.expander = expander;
      return _react2['default'].createElement('div', {
        ref: _this2.saveRef('tableNode'),
        className: className,
        style: props.style,
        id: props.id
      }, _this2.renderTitle(), _react2['default'].createElement('div', { className: prefixCls + '-content' }, _this2.renderMainTable(), hasLeftFixed && _this2.renderLeftFixedTable(), hasRightFixed && _this2.renderRightFixedTable()));
    }));
  };

  return Table;
}(_react2['default'].Component);

Table.propTypes = (0, _extends3['default'])({
  data: _propTypes2['default'].array,
  useFixedHeader: _propTypes2['default'].bool,
  columns: _propTypes2['default'].array,
  prefixCls: _propTypes2['default'].string,
  bodyStyle: _propTypes2['default'].object,
  style: _propTypes2['default'].object,
  rowKey: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].func]),
  rowClassName: _propTypes2['default'].oneOfType([_propTypes2['default'].string, _propTypes2['default'].func]),
  onRow: _propTypes2['default'].func,
  onHeaderRow: _propTypes2['default'].func,
  onRowClick: _propTypes2['default'].func,
  onRowDoubleClick: _propTypes2['default'].func,
  onRowContextMenu: _propTypes2['default'].func,
  onRowMouseEnter: _propTypes2['default'].func,
  onRowMouseLeave: _propTypes2['default'].func,
  showHeader: _propTypes2['default'].bool,
  title: _propTypes2['default'].func,
  id: _propTypes2['default'].string,
  footer: _propTypes2['default'].func,
  emptyText: _propTypes2['default'].oneOfType([_propTypes2['default'].node, _propTypes2['default'].func]),
  scroll: _propTypes2['default'].object,
  rowRef: _propTypes2['default'].func,
  getBodyWrapper: _propTypes2['default'].func,
  children: _propTypes2['default'].node,
  components: _propTypes2['default'].shape({
    table: _propTypes2['default'].any,
    header: _propTypes2['default'].shape({
      wrapper: _propTypes2['default'].any,
      row: _propTypes2['default'].any,
      cell: _propTypes2['default'].any
    }),
    body: _propTypes2['default'].shape({
      wrapper: _propTypes2['default'].any,
      row: _propTypes2['default'].any,
      cell: _propTypes2['default'].any
    })
  })
}, _ExpandableTable2['default'].PropTypes);
Table.childContextTypes = {
  table: _propTypes2['default'].any,
  components: _propTypes2['default'].any
};
Table.defaultProps = {
  data: [],
  useFixedHeader: false,
  rowKey: 'key',
  rowClassName: function rowClassName() {
    return '';
  },
  onRow: function onRow() {},
  onHeaderRow: function onHeaderRow() {},

  prefixCls: 'rc-table',
  bodyStyle: {},
  style: {},
  showHeader: true,
  scroll: {},
  rowRef: function rowRef() {
    return null;
  },
  emptyText: function emptyText() {
    return 'No Data';
  }
};

exports['default'] = Table;
module.exports = exports['default'];